package com.itheima.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.itheima.dao.FileMapper;
import com.itheima.dao.UserMapper;
import com.itheima.pojo.*;
import com.itheima.service.UserService;
import com.itheima.utils.CookieUtils;
import com.itheima.utils.IdWorker;
import com.itheima.utils.IpUtils;
import com.itheima.utils.TokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import tk.mybatis.mapper.entity.Example;


import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

   @Autowired
   private FileMapper fileMapper;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    //设置token标签
    private static final String BEARER = "bearer_";
    //设置redis中token的键标签
    private static final String LOGIN = "LOGIN_";


    /**
     * 用户列表展示
     *
     * @param userVO
     * @return
     */
    @Override
    public PageResult getList(UserVO userVO) {

        Integer currentPage = userVO.getCurrentPage();
        Integer pageSize = userVO.getPageSize();
        PageHelper.startPage(1, 10);

        Example example = new Example(User.class);
        Example.Criteria criteria = example.createCriteria();
        if(userVO.getKeyword()!=null&&!"".equals(userVO.getKeyword())){
            criteria.andEqualTo("nickName",userVO.getKeyword());
        }
        List<User> users = userMapper.selectByExample(example);

        PageInfo pageInfo = new PageInfo(users);
        return new PageResult(pageInfo.getTotal(), pageInfo.getList());

    }


    /**
     * 通过添加查询user
     *
     * @param user
     * @return
     */
    @Override
    public User getUser(User user) {
        return null;
    }

    /**
     * 根据uid删除用户
     *
     * @param uid
     * @return
     */
    @Override
    @Transactional
    public int delete(String uid) {
        User user = new User();
        user.setUid(uid);
        //根据uid删除用户信息
      return userMapper.delete(user);
    }


    /**
     * 根据用户id编辑用户信息
     *
     * @param userVO
     * @return
     */
    @Transactional
    public int edit(UserVO userVO) {

        User user = JSON.parseObject(JSON.toJSONString(userVO), User.class);
        user.setUpdateTime(new Date());
        Example example = new Example(User.class);
        Example.Criteria criteria = example.createCriteria();

        if (user.getUid() != null && !"".equals(user.getUid())) {
            criteria.andEqualTo("uid", user.getUid());
        }
        return userMapper.updateByExample(user, example);

    }

    @Override
    public Result login(UserVO userVO, HttpServletRequest request) {

        String userName = userVO.getUserName();
        String passWord = userVO.getPassWord();
        User user1 = new User();
        user1.setUserName(userName);

        User user = userMapper.selectOne(user1);
        //当前用户登录成功修改最近登录时间，修改增加登录次数，查询IP地址，响应cookie
        if (user != null) {

            if (bCryptPasswordEncoder.matches(passWord, user.getPassWord())) {
                //用户存在,并且密码正确，为登录成功
                Map<String, Object> claims = new HashMap<>();
                //设置载荷,token 中保存用户名和用户uid
                claims.put("username", user.getUserName());
                claims.put("uid", user.getUid());
                String token = TokenUtil.createJavaWebToken(claims);
                //用户登录成功，响应cookie，浏览器关闭，重新登录
                CookieUtils.setCookie("Authorization", BEARER + token, -1);
                redisTemplate.boundValueOps(LOGIN + user.getUserName()).set(BEARER + token, 60, TimeUnit.MINUTES);
                user.setLoginCount(user.getLoginCount() + 1);
                user.setLastLoginTime(new Date());
                String realIp = IpUtils.getRealIp(request);
                user.setLastLoginIp(realIp);
                //判断是否是内网IP
                boolean inner = IpUtils.isInner(realIp);
                if (inner) {
                    user.setIpSource("内网IP|内网IP");
                    Map<String, String> osAndBrowserInfo = IpUtils.getOsAndBrowserInfo(request);
                    String os = osAndBrowserInfo.get("OS");
                    String browser = osAndBrowserInfo.get("BROWSER");
                    user.setOs(os);
                    user.setBrowser(browser);
                    userMapper.updateByPrimaryKey(user);
                } else {
                    user.setIpSource(null);
                    Map<String, String> osAndBrowserInfo = IpUtils.getOsAndBrowserInfo(request);
                    String os = osAndBrowserInfo.get("OS");
                    String browser = osAndBrowserInfo.get("BROWSER");
                    user.setOs(os);
                    user.setBrowser(browser);
                    userMapper.updateByPrimaryKey(user);
                }
                return new Result(StatusCode.OK, "登录成功");
            }
            //返回用户登录结果
            return new Result(StatusCode.ERROR, "密码错误");
        }
        return new Result(StatusCode.ERROR, "用户名不存在");
    }

    @Override
    public User findUser1ByName(String userName) {
        User user = new User();
        user.setUserName(userName);
        return userMapper.selectOne(user);
    }

    @Override
    public int register(UserVO userVO, HttpServletRequest request) throws Exception {

        //注册，封装user对象
        User user = new User();
        user.setAvatar(userVO.getAvatar());
        user.setBirthday(DateUtils.parseString2Date(userVO.getBirthday()));
        user.setCommentStatus(userVO.getCommentStatus());
        user.setEmail(userVO.getEmail());
        user.setGender(Integer.valueOf(userVO.getGender()));
        user.setMobile(userVO.getMobile());
        user.setNickName(userVO.getNickName());

        user.setPassWord(bCryptPasswordEncoder.encode(userVO.getPassWord()));
        String ipAddr = IpUtils.getIpAddr(request); //获取当前网络ip
        user.setLastLoginIp(ipAddr);
        user.setLastLoginTime(new Date());
        user.setLoginCount(0);

        user.setQqNumber(userVO.getQqNumber());
        user.setSource(userVO.getSource());
        user.setSummary(userVO.getSummary());
        user.setUid(idWorker.nextId() + "");
        user.setUserName(userVO.getUserName());
        user.setUuid(UUID.randomUUID().toString());
        user.setStartEmailNotification(userVO.getStartEmailNotification());
        user.setStatus(userVO.getStatus());
        user.setUserTag(userVO.getUserTag());
        user.setUpdateTime(new Date());
        user.setCreateTime(new Date());

        //判断是否是内网IP
        boolean inner = IpUtils.isInner(ipAddr);
        if (inner) {
            user.setIpSource("内网IP|内网IP");
            Map<String, String> osAndBrowserInfo = IpUtils.getOsAndBrowserInfo(request);
            String os = osAndBrowserInfo.get("OS");
            String browser = osAndBrowserInfo.get("BROWSER");
            user.setOs(os);
            user.setBrowser(browser);
            return userMapper.insert(user);

        } else {
            user.setIpSource(null);
            Map<String, String> osAndBrowserInfo = IpUtils.getOsAndBrowserInfo(request);
            String os = osAndBrowserInfo.get("OS");
            String browser = osAndBrowserInfo.get("BROWSER");
            user.setOs(os);
            user.setBrowser(browser);
            return userMapper.insert(user);
        }

    }

    //查询用户旧密码是否正确
    @Override
    public User findUserBypassWord(String oldPwd) {
         User user = new User();
         user.setPassWord(oldPwd);
        return userMapper.selectOne(user);
    }

    //修改用户密码
    @Override
    public int updatePassWord(Map map) {
        String newPwd = (String) map.get("newPwd");
        String uid= (String) map.get("uid");
        User user = new User();
        user.setPassWord(newPwd);
        user.setUid(uid);
        return userMapper.updateByPrimaryKey(user);
    }

    // 获取用户信息
    @Override
    public Map<String, Object> verify(String username) throws Exception {

        //1 查询当前用户对应的角色id avatar
        Map<String,Object> map=userMapper.findVerify(username);
        Date createTime = (Date) map.get("createTime");
        Date updateTime = (Date) map.get("updateTime");
        Date lastLoginTime = (Date) map.get("lastLoginTime");
        String createTime2 = DateUtils.parseDate2String(createTime);
        String updateTime2= DateUtils.parseDate2String(updateTime);
        String lastLoginTime2= DateUtils.parseDate2String(lastLoginTime);
        map.put("createTime",createTime2);
        map.put("updateTime",updateTime2);
        map.put("lastLoginTime",lastLoginTime2);

        return map;

    }

    /**
     * 重置用户密码
     * @param userVO
     */
    @Override
    public void resetUserPassword(UserVO userVO) {
        //重置密码后的用户的密码是000000
        String defaultPassword = "000000";
        User user = JSON.parseObject(JSON.toJSONString(userVO), User.class);
        String uid = user.getUid();
        user.setUpdateTime(new Date());
        user.setPassWord(defaultPassword);
        User user1 = userMapper.selectByPrimaryKey(uid);
        user.setUserName(user1.getUserName());
        user.setStatus(user1.getStatus());
        user.setCommentStatus(user1.getCommentStatus());
        user.setStartEmailNotification(user1.getStartEmailNotification());
        user.setUserTag(user1.getUserTag());
        Example example = new Example(User.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("uid",uid);

        userMapper.updateByExample(user,example);

    }


    /**
     * 根据uid查询user
     *
     * @param uid
     * @return
     */
    @Override
    public User getUserByUid(String uid) {
        return userMapper.getUserByUid(uid);
    }

    private Example createExample(Map<String, Object> param) {
        Example example = new Example(Comment.class);
        Example.Criteria criteria = example.createCriteria();
        if (param != null) {
            // 用户名
            if (param.get("userName") != null && !"".equals(param.get("userName"))) {
                criteria.andEqualTo("userName", param.get("userName"));
            }
            // 评论内容
            if (param.get("content") != null && !"".equals(param.get("content"))) {
                criteria.andEqualTo("content", param.get("content"));
            }
            // 评论来源
            if (param.get("source") != null && !"".equals(param.get("source"))) {
                criteria.andEqualTo("source", param.get("source"));
            }
            // 播客uid
            if (param.get("blogUid") != null && !"".equals(param.get("blogUid"))) {
                criteria.andEqualTo("blogUid", param.get("blogUid"));
            }
            // 状态
            if (param.get("status") != null && !"".equals(param.get("status"))) {
                criteria.andEqualTo("status", param.get("status"));
            }
            // 回复某条评论的uid
            if (param.get("toUid") != null && !"".equals(param.get("toUid"))) {
                criteria.andEqualTo("toUid", param.get("toUid"));
            }
            // 回复某个人的uid
            if (param.get("toUserUid") != null && !"".equals(param.get("toUserUid"))) {
                criteria.andEqualTo("toUserUid", param.get("toUserUid"));
            }
            // 评论名
            if (param.get("type") != null && !"".equals(param.get("type"))) {
                criteria.andEqualTo("type", param.get("type"));
            }
            // 评论类型
            if (param.get("uid") != null && !"".equals(param.get("uid"))) {
                criteria.andEqualTo("uid", param.get("uid"));
            }
            // 用户uid
            if (param.get("userUid") != null && !"".equals(param.get("userUid"))) {
                criteria.andEqualTo("userUid", param.get("userUid"));
            }
        }
        return example;
    }
}
